package com.aabte.weather.wearthercollection.weather;

import com.aabte.weather.wearthercollection.weather.dto.WeatherResponse;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * 天气数据采集服务
 */
@Slf4j
@Service
public class WeatherDataCollectionServiceImpl implements WeatherDataCollectionService {
    private static final String WEATHER_API = "http://wthrcdn.etouch.cn/weather_mini";

    @Resource
    private RestTemplate restTemplate;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private WeatherProperties weatherProperties;

    @Override
    public void syncDataByCityId(String cityId) {
        getDataByCityId(cityId);
    }

    private WeatherResponse getDataByCityId(String cityId) {
        return doGetWeatherData(cityId);
    }

    private WeatherResponse doGetWeatherData(String cityIdOrCityName) {
        ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();

        String cacheKey = cityIdOrCityName;
        String responseBody;

        if (StringUtils.isBlank(responseBody = ops.get(cacheKey))) {
            log.info("start from remote get weather. cityIdOrCityName: {}", cityIdOrCityName);
            ResponseEntity<String> responseEntity = restTemplate.getForEntity(buildUrl(cityIdOrCityName), String.class);
            log.info("end from remote get weather.");
            if (responseEntity.getStatusCodeValue() != HttpStatus.OK.value()
                    || StringUtils.isBlank(responseBody = responseEntity.getBody())) {
                log.warn("from remote get weather failed. cityIdOrCityName: {}", cityIdOrCityName);
                return null;
            }
            ops.set(cacheKey, responseBody, weatherProperties.getCacheTimeoutSeconds(), TimeUnit.SECONDS);
        } else {
            log.info("from cache get weather success. cityIdOrCityName: {}", cityIdOrCityName);
        }

        ObjectMapper mapper = new ObjectMapper();
        try {
            return mapper.readValue(responseBody, WeatherResponse.class);
        } catch (JsonProcessingException e) {
            log.error("deserialization failed. cityIdOrCityName: {}", cityIdOrCityName, e);
        }
        return null;
    }

    private String buildUrl(String cityIdOrCityName) {
        if (StringUtils.isNumeric(cityIdOrCityName)) {
            return WEATHER_API + "?citykey=" + cityIdOrCityName;
        }
        return WEATHER_API + "?city=" + cityIdOrCityName;
    }
}
